﻿using System;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using DyUi.Base;
using DyUi.Base.Interfaces;
using DyUi.Base.Interfaces.Services;
using DyUi.Core;
using DyUi.Interfaces;
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;

namespace DyUi.ScriptHost.IronPython
{
    [Export(typeof(IExecutionService))]
    [ScriptHostMetaData("IronPython", "py")]
    public class IronPythonExecutionService : DyUiService, IExecutionService
    {
        ScriptEngine _engine;
        ScriptScope _scope;

        dynamic _controlScriptHelper;

        dynamic _controlScriptObject;

        public override void Prepare()
        {
            base.Prepare();

            var control = (IDyUiControl)Component;

            _engine = Python.CreateEngine();
            _engine.SetSearchPaths(new[] { @"C:\Program Files (x86)\IronPython 2.6 for .NET 4.0 RC\Lib" });
            _scope = _engine.CreateScope();

            var serviceScriptFile = GetType().Name + ".py";

            if (File.Exists(serviceScriptFile))
                ExecuteFile(serviceScriptFile);

            var controlScriptFile = Path.Combine(control.Path.FullName, control.DyUiName + ".py");

            if (File.Exists(controlScriptFile))
            {
                ExecuteFile(controlScriptFile);

                _controlScriptHelper = ExecuteLine(String.Format("{0}()", GetType().Name));
                
                var settings = (Object)_controlScriptHelper.get_settings(control) ?? new Object(); // There seems to be some oddness with nulls and casting a dynamic to object in a method call.

                SetVariable("__control__", control);
                SetVariable("__controlSettings__", settings);

                _controlScriptObject = ExecuteLine(String.Format("{0}(__control__, __controlSettings__)", control.DyUiName));

                ((UserControl)control).DataContext = _controlScriptObject;
            }
        }

        public object ExecuteFile(String path)
        {
            return _engine.ExecuteFile(path, _scope);
        }

        public object ExecuteLine(String line)
        {
            return _engine.Execute(line, _scope);
        }

        public void SetVariable(String name, Object value)
        {
            _scope.SetVariable(name, value);
        }

        public dynamic GetVariable(String name, Object value)
        {
            return _scope.GetVariable(name);
        }

        public void RouteEvent(Object sender, RoutedEventArgs e)
        {
            if (_controlScriptHelper == null)
                return;

            _controlScriptHelper.route_default(_controlScriptObject, sender, e);
        }

        public void PrepareControlScriptObject()
        {
            if (_controlScriptHelper == null)
                return;

            _controlScriptHelper.prepare_control_script_object(_controlScriptObject);
        }

    }
}
